package liquor.util;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import liquor.exception.LiquorException;

public class CommonUtil {
	
	/**
	 * 오라클의 NVL과 같은 함수</br>
	 * 사용예</br>
	 * <pre>
	 * String a;
	 * a = CommonUtil.nvl(a, "5");
	 * </pre>
	 * 
	 * @param value
	 * @param defaultValue
	 */
	public static <T> T nvl(T value, T defaultValue) {
		return value == null ? defaultValue : value;
	}
	
	/**
	 * 리스트가 비어있는지 확인하는 함수</br>
	 * 리스트가 NULL 이거나, 비어있을경우 true
	 * @param list
	 * @return boolean
	 */
	public static <T extends Object> boolean isEmpty(List<T> list) {
		return list == null || list.isEmpty();
	}
	
	
	/**
	 * 입력 객체의 필드의 Null 체크
	 * 입력인자가 가지는 필드중 Null 이면 안되는 값들을 체크해서 Null 이면 {@link LiquorException}을 던진다.
	 * 이때, fieldNames에 있는 항목이 객체에 없으면 이때도 LiquorException을 던진다.
	 * 
	 * 
	 * ex1) CommonUtil.nullCheck(inVO, "name", "rrn", "address");
	 * --> inVO의 변수중 address가 없으면
	 *     -> "address필드가 존재하지 않습니다" 익셉션
	 * 
	 * ex2) CommonUtil.nullCheck(inVO, "name", "rrn");
	 * --> rrn의 getter가 존재 하지 않을경우 (getRrn())
	 *     -> "rrn" 필드에 접근할수 없습니다.
	 * 
	 * ex3) CommonUtil.nullCheck(inVO, "name", "rrn");
	 * --> inVO의 변수중 rrn이 NULL이면
	 *     -> "rrn은 필수값입니다." 익셉션 
	 * 
	 *     
	 * 
	 * 
	 * 우선순위) 변수체크, 필수값 체크
	 */
	public static <T> void nullCheck(T obj, String ... fieldNames) {
		
		Class<?> clazz = obj.getClass();
		Field[] fields = clazz.getDeclaredFields();
				
		List<String> fieldList = new ArrayList<String>();
		for (int i=0 ; i<fields.length ; i++) {
			fieldList.add(fields[i].getName());
		}
		
		// 1. 입력인자의 존재유무 체크
		for (int i=0 ; i<fieldNames.length ; i++) {
			String fieldName = fieldNames[i];
			if (!fieldList.contains(fieldName)) {
				throw new LiquorException("입력("+ clazz.getSimpleName() + ")의 필드(" + fieldName + ")가 존재하지 않습니다.");
			}
		}
		
		// 2. 입력인자 NULL 체크
		for (int i=0 ; i<fieldNames.length ; i++) {
			String fieldName = fieldNames[i];
			String getterName = Core.createGetterName(fieldName);
			
			Method m = null;
			try {
				m = clazz.getMethod(getterName);
			} catch(NoSuchMethodException e) {
				throw new LiquorException("입력(" + clazz.getSimpleName() + ")의 필드(" + fieldName + ")에 접근할 수 없습니다.");
			}
			
			Object o;
			try {
				o = m.invoke(obj);
			} catch (Exception e) {
				throw new LiquorException("치명적인 오류발생");
			}
			
			if (o == null) {
				throw new LiquorException("입력(" + clazz.getSimpleName() + ")의 필드(" + fieldName+ ")은 필수값입니다.");
			}
		}
	}
}
